//
// Created by luxiangyang on 2025/4/9.
//
#ifndef SERIALIZECOMM_CCOMSERIALIZETOOL_H
#define SERIALIZECOMM_CCOMSERIALIZETOOL_H
#include "json.hpp"
namespace nlohmann{
    template <class T>
    inline void safety_from(const json &j,const char *key,T &o)
    {
        auto it=j.find(key);
        if(it!=j.end())
            it->get_to(o);
    }
}

#define CCOMSERIALIZETOOL_EXPAND(x) x
#define CCOMSERIALIZETOOL_REPEAT_VAR_COUNT(count) CCOMSERIALIZETOOL_EXPAND_M##count
#define CCOMSERIALIZETOOL_EXPAND_APPLY(macro,...) CCOMSERIALIZETOOL_EXPAND(macro(__VA_ARGS__))

#define CCOMSERIALIZETOOL_REPEAT(macro,data,...)                                                        \
        CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_APPLY(                                        \
        CCOMSERIALIZETOOL_REPEAT_VAR_COUNT,                                                             \
        CCOMSERIALIZETOOL_REPEAT_COUNT(__VA_ARGS__))(macro,data,__VA_ARGS__))

#define CCOMSERIALIZETOOL_EXPAND_M1(m,d,x) m(d,0,x)
#define CCOMSERIALIZETOOL_EXPAND_M2(m,d,x,...)                                                   \
    m(d,1,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M1(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M3(m,d,x,...)                                                   \
    m(d,2,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M2(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M4(m,d,x,...)                                                   \
    m(d,3,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M3(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M5(m,d,x,...)                                                   \
    m(d,4,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M4(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M6(m,d,x,...)                                                   \
    m(d,5,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M5(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M7(m,d,x,...)                                                   \
    m(d,6,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M6(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M8(m,d,x,...)                                                   \
    m(d,7,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M7(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M9(m,d,x,...)                                                   \
    m(d,8,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M8(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M10(m,d,x,...)                                                   \
    m(d,9,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M9(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M11(m,d,x,...)                                                   \
    m(d,10,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M10(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M12(m,d,x,...)                                                   \
    m(d,11,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M11(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M13(m,d,x,...)                                                   \
    m(d,12,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M12(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M14(m,d,x,...)                                                   \
    m(d,13,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M13(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M15(m,d,x,...)                                                   \
    m(d,14,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M14(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M16(m,d,x,...)                                                   \
    m(d,15,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M15(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M17(m,d,x,...)                                                   \
    m(d,16,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M16(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M18(m,d,x,...)                                                   \
    m(d,17,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M17(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M19(m,d,x,...)                                                   \
    m(d,18,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M18(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M20(m,d,x,...)                                                   \
    m(d,19,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M19(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M21(m,d,x,...)                                                   \
    m(d,20,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M20(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M22(m,d,x,...)                                                   \
    m(d,21,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M21(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M23(m,d,x,...)                                                   \
    m(d,22,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M22(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M24(m,d,x,...)                                                   \
    m(d,23,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M23(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M25(m,d,x,...)                                                   \
    m(d,24,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M24(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M26(m,d,x,...)                                                   \
    m(d,25,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M25(m,d,__VA_ARGS__))
#define CCOMSERIALIZETOOL_EXPAND_M27(macro,data,x,...)                                                   \
    m(d,26,x) CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_EXPAND_M26(m,d,__VA_ARGS__))


#define CCOMSERIALIZETOOL_REPEAT_COUNT_IMPLICIT( \
    _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,count,...)\
count

#define CCOMSERIALIZETOOL_REPEAT_COUNT(...) \
    CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_REPEAT_COUNT_IMPLICIT(    \
    __VA_ARGS__,27,26,25,24,23,22,21,20,19,18,\
    17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1))

#define CCOMSERIALIZETOOL_GET(j,ignore,x) nlohmann::safety_from(j,#x,o._##x);
#define CCOMSERIALIZETOOL_SET(j,ignore,x) j[#x] = o._##x;
#define Serializable(TYPE,...)                                                                  \
    void from_json(const nlohmann::json &j,TYPE &o)                                             \
    {                                                                                           \
      CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_REPEAT(CCOMSERIALIZETOOL_GET,j,__VA_ARGS__))   \
    }                                                                                           \
                                                                                                \
    void to_json(nlohmann::json &j,const TYPE &o)\
    {                                                                                           \
      CCOMSERIALIZETOOL_EXPAND(CCOMSERIALIZETOOL_REPEAT(CCOMSERIALIZETOOL_SET,j,__VA_ARGS__))   \
    }
#endif //SERIALIZECOMM_CCOMSERIALIZETOOL_H
